import Cocoa
import FlutterMacOS
import IOKit
import IOKit.usb

public class JmUsbPlugin: NSObject, FlutterPlugin {
    let vendorID: UInt16 = 0x1234
    let productID: UInt16 = 0x5678
    var activeDevice: io_service_t? = nil
    var usbDeviceList: [UsbDevice] = []

    public static func register(with registrar: FlutterPluginRegistrar) {
        let channel = FlutterMethodChannel(name: "jm_usb_method_channel",
                                           binaryMessenger: registrar.messenger)
        let instance = JmUsbPlugin()
        registrar.addMethodCallDelegate(instance, channel: channel)
    }

    public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
        print("Received method call: \(call.method)")
        switch call.method {
        case "getPlatformVersion":
            result("macOS " + ProcessInfo.processInfo.operatingSystemVersionString)
        case "getDeviceList":
            scanAllUSBDevices()
            result(usbDeviceList.map { $0.toMap() })
        default:
            result(FlutterMethodNotImplemented)
        }
    }

    private func scanAllUSBDevices() {
        guard let matchingDict = IOServiceMatching(kIOUSBDeviceClassName) else {
            print("Failed to create matching dictionary")
            return
        }

        var iterator: io_iterator_t = 0
        defer { IOObjectRelease(iterator) } // 自动释放迭代器资源

        let result = IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict, &iterator)
        usbDeviceList.removeAll()

        if result != KERN_SUCCESS {
            print("获取USB设备列表失败，错误码: \(result)")
            return
        }

        print("成功获取USB设备列表")
        iterateDevices(iterator: iterator)
    }

    private func iterateDevices(iterator: io_iterator_t) {
        var device: io_object_t = IOIteratorNext(iterator)
        while device != 0 {
            if let usbDevice = createUsbDevice(from: device) {
                usbDeviceList.append(usbDevice)
            }
            IOObjectRelease(device) // 释放设备对象
            device = IOIteratorNext(iterator)
        }
    }

    private func createUsbDevice(from device: io_object_t) -> UsbDevice? {
        guard
            let productName = getUSBProductName(device: device),
            let vendorID = getUSBProperty(device: device, key: kUSBVendorID) as? Int,
            let productID = getUSBProperty(device: device, key: kUSBProductID) as? Int,
            let configurationCount = getUSBProperty(device: device, key: kUSBDeviceNumConfigs) as? Int
        else {
            print("无法获取设备的完整信息")
            return nil
        }

        let identifier = "\(productName)-\(vendorID)-\(productID)"
        print("""
        设备名称: \(productName)
        Vendor ID: \(vendorID)
        Product ID: \(productID)
        Configuration Count: \(configurationCount)
        """)

        return UsbDevice(
            identifier: identifier,
            deviceName: productName,
            manufacturerName: nil,
            productName: productName,
            serialNumber: nil,
            vendorId: vendorID,
            productId: productID,
            configurationCount: configurationCount,
            configurations: []
        )
    }
    
    func openDevice(vid: Int, pid: Int) -> Bool {
       
        var score: Int32 = 0
        var pluginInterfacePtrPtr: UnsafeMutablePointer<UnsafeMutablePointer<IOCFPlugInInterface>?>?

        let kr = IOCreatePlugInInterfaceForService(
            activeDevice!,
            kIOUSBDeviceUserClientTypeID,
            kIOCFPlugInInterfaceID,
            &pluginInterfacePtrPtr,
            &score
        )

        guard kr == KERN_SUCCESS, let pluginInterfacePtr = pluginInterfacePtrPtr else {
            print("无法创建插件接口")
            return false
        }

        let pluginInterface = pluginInterfacePtr.pointee!
        var deviceInterfacePtrPtr: UnsafeMutablePointer<UnsafeMutablePointer<IOUSBDeviceInterface>?>?

        let result = withUnsafeMutablePointer(to: &deviceInterfacePtrPtr) {
            $0.withMemoryRebound(to: Optional<LPVOID>.self, capacity: 1) {
                pluginInterface.pointee.pointee.QueryInterface!(
                    pluginInterfacePtr,
                    CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID),
                    $0
                )
            }
        }

        guard result == kIOReturnSuccess, let deviceInterfacePtr = deviceInterfacePtrPtr else {
            print("无法获取设备接口")
            return false
        }

        self.deviceInterface = deviceInterfacePtr.pointee!
        return self.deviceInterface?.pointee.USBDeviceOpen(self.deviceInterface) == kIOReturnSuccess
    }

    private func getUSBProductName(device: io_object_t) -> String? {
        return getUSBProperty(device: device, key: kUSBProductString) as? String
    }

    private func getUSBProperty(device: io_object_t, key: String) -> Any? {
        let property = IORegistryEntryCreateCFProperty(device, key as CFString,
                                                       kCFAllocatorDefault, 0)
        return property?.takeRetainedValue()
    }
}
